www.gusucode.com > XerCMS 携云PHP企业建站程序 v2015PHP源码程序 > XerCMS 携云PHP企业建站程序 v2015/XerCMS_v20150724/XerCMS_v20150724/XerCMS/Library/XerCMS_compiler.php

    <?php
/**
 * @name     XERCMS
 * @author   Arno <XerCMS@163.com> [QQ:1328013]
 * @version  1.0.0
 * @link     http://www.XerCMS.com 
 */

!defined('XERCMS') && exit('Access Denied');

class compiler
{
     private $temp    = '';
	private $html    = '';
	private $result  = '';
	private $tplDir  = '';	 
	private $currDir = '';
	private $cInst   = NULL;
	public  $cacheId = '';
	public  $phpstr = array();
	public  $embeds = NULL;	 
	public  $pregVer  = NULL;
	public  $data_Id = 0;
     private $links;
     public $valName = '';
      
	public function Set($dir,$file,$cacheId = '') {
	     $this->cacheId =  empty($cacheId) ? md5($dir.$file) : $cacheId;
	     $this->tplDir = $dir;
		$this->currDir = dirname($dir.$file).'/';
	 	$this->html = $this->tpl($file);	    
	}
	
	public function tpl($file) {
	     if($file == NULL)
		     return '';
	     if(strpos($file,'/') !== false) {
		     $file = $this->tplDir.$file;
		} else $file = $this->currDir.$file;
          $file = XERCMS.$file;
	     if(is_file($file)) {
		     return file_get_contents($file);
		} else throw new TpError($file.' is not exist!');
	}
	 
	 
	 
	public function php($method = 'hide',$data = '') {
	     switch($method) {
		 	case 'hide':
	 	 	 	if(strpos($this->html,'{XERCMS:eval}') !== false && strpos($this->html,'{end:eval}') !== false) {
		      	 	$this->html = $this->preg('/{XERCMS\:eval}(.*?){end\:eval}/is',function ($match){return X::$compiler->php('code',$match[1]);},$this->html);
	 	 	 	}
			break;
			case 'show':
			     foreach($this->phpstr as $k=>$v) {
				     $rep['{php#'.$k.'}{/php}'] = '<?php '.$v.' ?>';
				}
			     if(empty($rep))
				     return;
				$this->html = strtr($this->html,$rep);
			break;
			case 'code':
			     if(empty($data))
				      return '';
			     $key = count($this->phpstr);
			     $this->phpstr[$key] = $data;
				return '{php#'.$key.'}{/php}';
         	 	break;			 
		}
	}
	 
	private function sub() {   
	     $max = 5;
	     $hasSub = strpos($this->html,'{XERCMS#');
		while($hasSub !== false && $max > 0) {
		     $this->html = $this->preg('/{XERCMS\#([a-z0-9\_\/\.]+)}/is',function($match){return X::$compiler->tpl($match[1]);},$this->html);
			$hasSub = strpos($this->html,'{XERCMS#');
			$max--;
		}
	}
	 
	public function ads() {
	     $this->html = preg_replace_callback('/{XERCMS\$G\[ads\]\[([0-9]+)\]}/is',function($match){return '<?php echo ads('.$match[1].');?>';},$this->html);
	}
	 
	public function quote($str) {
		return $this->preg('/\[([a-zA-Z0-9\_]+)\]/','[\'\\1\']',$str,false);
	}
	 
	public function v() {
	 	$this->html = $this->preg('/{XERCMS\$([a-zA-Z0-9\$\[\]\_\'\.\"]+)}/is',function($match){return '<?php echo $'.trim(preg_replace('/\[([a-zA-Z0-9\_]+)\]/','[\'\\1\']',$match[1])).';?>';},$this->html);
	}

	public function txt() {
	 	$this->html = $this->preg('/{XERCMS\@([a-zA-Z0-9\$\[\]\_\'\"]+)}/is',function($match){return '<?php echo htmlchars($'.trim(preg_replace('/\[([a-zA-Z0-9\_]+)\]/','[\'\\1\']',$match[1])).');?>';},$this->html);
	}
	 
	public function values() {
	 	$this->html = $this->preg('/{XERCMS\&([a-zA-Z0-9\_]+)\(([a-zA-Z0-9\[\]\$\_\'\"]+)\)}/is',function($match){return '<?php echo sVar(\''.$match[1].'\','.(strpos($match[2],'$') === 0 ? '' : '$').X::$compiler->quote($match[2]).'); ?>';},$this->html);
	}
	 
	public function i() {	 
	 	if(strpos($this->html,'{XERCMS:if') !== false) {

			$this->html = $this->preg('/{XERCMS:if ([^\}]*?)}/is',function($match){return '<?php if ('.X::$compiler->preg('/\[([a-zA-Z0-9\_]+)\]/','[\'\\1\']',$match[1],false).') { ?>';},$this->html);		 
	 	 	$this->html = strtr($this->html,array('{end:if}'=>'<?php } ?>'));
	 	 	if(strpos($this->html,'{XERCMS:else}') !== false) {
	 	 	 	$this->html = strtr($this->html,array('{XERCMS:else}'=>'<?php } else { ?>'));
	 	 	}
	 	     if(strpos($this->html,'{XERCMS:elseif') !== false) {
				$this->html = $this->preg('/{XERCMS:elseif ([^\}]*?)}/is',function($match){return '<?php } else if ('.X::$compiler->quote($match[1]).') { ?>';},$this->html);
	 	 	}
	 	}
	}
	 
	public function fun($method = '',$name = '',$params = '') {
	     switch($method) {
		 	case 'php':
	 	 	 	$params = strtr(trim($params),array(']'=>'\']','['=>'[\''));
	 	 	 	return '<?php echo '.$name.'('.$params.');?>';
			break;
		     default:
	 	 	 	if(strpos($this->html,'{XERCMS!') !== false)
	 	 	 	 	$this->html = $this->preg('/{XERCMS!([a-z0-9\_]+)\((.*?)\)}/is',function($match){return X::$compiler->fun('php',$match[1],$match[2]);},$this->html);
			break;	
		}			 
	}

	private function param($attr) {
	 	if(!is_array($attr) || count($attr) !== 2) {
	 	 	return array();
	 	}
	 	$ret = array();
	 	foreach($attr[1] as $k=>$v) {
	 	 	$ret[$v] = isset($attr[2][$k]) ?  $attr[2][$k] : '';
	 	}
	 	return $ret;
	}
	 
	private function vars($params) {
	     foreach($params as $k=>$str) {
		     $str = trim($str);
		     $params[$k] = strpos($str,'&') === 0 ? '$'.trim(strtr(preg_replace('/\[([a-zA-Z0-9\_]+)\]/','[\'\\1\']',$str),array('&'=>''))) : (strpos($str,'$') === 0 ? $this->quote($str) : $str);
		}
	     return $params;
	}
  
     public function arr($param,$html) {
	     return '<?php foreach($'.preg_replace('/\[([a-zA-Z0-9\_]+)\]/','[\'\\1\']',$param['name']).' as '.(isset($param['index']) ? '$'.$param['index'].'=>' : '').'$'.$param['data'].') { ?>'.$html.'<?php } ?>';
	}
	 
	public function page($param,$html,$layer) {
	     if(empty($param['data']) || empty($param['total']) || empty($param['current']) || empty($param['range']))
		     return $html;
	     $php  = '<?php ';$param['range'] = (int)$param['range'];
	     $php .= '$'.$param['data'].'[\'URL\'] = '.((strpos($param['url'],'$') === 0) ? $param['url'] : '\''.$param['url'].'\'').';';
	     $php .= '$'.$param['data'].'[\'total\'] = '.((strpos($param['total'],'$') === 0) ? $param['total'] : '\''.$param['total'].'\'').';';
		$php .= '$'.$param['data'].'[\'current\'] = '.((strpos($param['current'],'$') === 0) ? $param['current'] : '\''.$param['current'].'\'').';';
	     $php .= '$'.$param['data'].'[\'pre\'] = '.$param['current'].' < 1 ? 1 : ('.$param['current'].' - 1);';
	     $php .= '$'.$param['data'].'[\'next\'] = '.$param['current'].' > '.$param['total'].' ? '.$param['total'].' : ('.$param['current'].' + 1);';	  
	     $php .= '$'.$param['data'].'[\'preURL\'] = strtr($'.$param['data'].'[\'URL\'],array(\'[page]\'=>$'.$param['data'].'[\'pre\']));';
	     $php .= '$'.$param['data'].'[\'nextURL\'] = strtr($'.$param['data'].'[\'URL\'],array(\'[page]\'=>$'.$param['data'].'[\'next\']));';	
	     $php .= '$'.$param['data'].'[\'totalURL\'] = strtr($'.$param['data'].'[\'URL\'],array(\'[page]\'=>$'.$param['data'].'[\'total\']));';
	     $php .= '$'.$param['data'].'[\'currentURL\'] = strtr($'.$param['data'].'[\'URL\'],array(\'[page]\'=>$'.$param['data'].'[\'current\']));';	
	     $php .= '$'.$param['data'].'[\'pages\'] = pages($'.$param['data'].'[\'total\'],$'.$param['data'].'[\'current\'],'.$param['range'].',$'.$param['data'].'[\'URL\']);';
		  
          $php .= ' ?>'.$html;
		return $php;
	}
	 
	public function table($param,$html,$layer) {
	     if(empty($param['from']))
		     return 'table is empty!';
          if(isset($param['cache'])) {
               $cache = (int)$param['cache'];
               unset($param['cache']);
          }  
	     $sql  = 'SELECT '.(isset($param['field']) && !empty($param['field']) ? $param['field'] : ' * ').' FROM '.$param['from'];
		$sql .= isset($param['left']) ? ' LEFT JOIN '.$param['left'] : '';$limit = isset($param['limit']) && !empty($param['limit']) ? ' LIMIT '.$param['limit'] : ' LIMIT 15 ';
          if(isset($param['index'])) {
               $key = '$'.$param['index'].'=>';
               unset($param['index']);
          } else $key = '';	
          if(isset($param['data'])) {
               $value = '$'.$param['data'];
               unset($param['data']);
          } else $value = '$val';
		unset($param['field'],$param['left'],$param['from'],$param['limit'],$param['data'],$param['index']);  
		foreach($param as $k=>$v) {   
		     $where[] = '`'.trim($k).'` = '.(strpos($v,'$') === 0 ? '\'.'.$v.'.\'' : '\''.$v.'\'');
		}
		if(!empty($where)) { 
		     $where = ' WHERE '.implode(' AND ',$where);
		} else $where = '';
		$sql .= $where.$limit;
		return '<?php $data_'.$layer.' = '.(isset($cache) ? 'Cache::fetchSql(\''.$sql.'\','.$cache.')' : 'DB::fetch_all(\''.$sql.'\')').';foreach($data_'.$layer.' as '.$key.$value.') { ?>'.$html.'<?php } ?>';
     }
	  
    
           
     public function data($param,$html,$layer) {
          $ret = '';
          if(isset($param['cache'])) {
               $cache = (int)$param['cache'];
               unset($param['cache']);
          }
          if(isset($param['id'])) {
               $data_select = DB::result('SELECT * FROM XERCMS_select_data WHERE id = \''.(int)$param['id'].'\'');
               if(isset($data_select['state']) && $data_select['state'] == 0) {
                    if(preg_match_all('/{XERCMS\$([0-9a-z\_]+)}/i',$data_select['sql'],$match)) {
                         foreach($match[1] as $v) {
                              if(!isset($param[$v])) {
							return 'Param Error!'; 
                              }
                         }
                         unset($param['id']);$repl = array();
                         foreach($param as $k=>$v) {
                              $repl['{XERCMS$'.$k.'}'] = $v;                         
                         }   
                         $data_select['sql'] = strtr($data_select['sql'],$repl);              
                    }
                    $this->data_Id++;
                    if($data_select['format'] == 1 ) {
                         return '<?php echo json_encode('.(isset($cache) ? 'Cache::fetchSql(\''.addslashes($data_select['sql']).'\','.$cache.')' : 'DB::fetch_all(\''.addslashes($data_select['sql']).'\')').');?>';
                    } else {
                         $name = 'data_sql_'.$this->data_Id;
                         return '<?php $'.$name.' = '.(isset($cache) ? 'Cache::fetchSql(\''.addslashes($data_select['sql']).'\','.$cache.')' : 'DB::fetch_all(\''.addslashes($data_select['sql']).'\')').';?>'.strtr($data_select['template'],array('name="__name__"'=>'name="'.$name.'"'));
                    } 
               }
          }
          return $ret;
     }
      
     private function link($param,$html,$layer) {
          if(empty(X::$CONFIG['#links'])) {
               X::$CONFIG['#links'] = ini('links/'.X::$CONFIG['urlmode']);
          }
          if(!isset($param['rule']) || empty($param['rule'])) {
               return '#';
          }
          if(isset(X::$CONFIG['#links'][$param['rule']])) {
               if(empty($html)) {
                    return $this->preg('/\{([0-9a-zA-Z\_]+)\}/',function($match){return '';},X::$CONFIG['#links'][$param['rule']]);  
               } else {
                    X::$compiler->valName = trim($html);
                    return $this->preg('/\{([0-9a-zA-Z\_]+)\}/',function($match){return '<?php echo urlParam(\''.$match[1].'\',$'.X::$compiler->valName.','.(X::$CONFIG['urlmode'] == 'dynamic' ? 1 : 0).');?>';},X::$CONFIG['#links'][$param['rule']]);     
               }
          } else return '#';
     }
     
	public function tag($name,$param,$html) {
	     if($name == 'embed')
		     return $this->embed($html);
		 
	 	if(preg_match_all('/([a-zA-Z0-9]+)=[\'"]([^\'"]+)[\'"]/',$param,$attr)) {//echo $param;print_r($attr);
	 	 	unset($attr[0]);$param = $this->vars($this->param($attr));
	 	} else $param = array();
		 
	 	$html = stripslashes($html);
		$name = str_replace('#','',$name,$layer);
	 	if(!empty($name)) {
		     if($name == 'array')
			     return $this->arr($param,$html);
		     if($name == 'table')
			     return $this->table($param,$html,$layer);	
		     if($name == 'page')
			     return $this->page($param,$html,$layer);	
		     if($name == 'data')
			     return $this->data($param,$html,$layer);	
		     if($name == 'link')
			     return $this->link($param,$html,$layer);                
			 /*if($name == 'sql')
			      return $this->sql($attr).$html.'<?php } ?>';*/
	 	 	global $XERCMS;$CLASS = 'XERCMS_TAG_'.strtoupper($name);
	 	 	if(isset($XERCMS[$CLASS]) == false) {
	 	 	 	$TagFile = '';$param['name'] = isset($param['name']) ? $param['name'] : $name;
	 	 	 	if($name == 'plugin') {
	 	 	 	 	$TagFile = XERCMS.'XerCMS/Plugins/'.$param['name'].'/XerCMS_TAG_'.$param['name'].'.php';
	 	 	 	} else {
				     $TagFile = XERCMS.'XerCMS/Modules/'.$name.'/tag/XerCMS_'.$param['name'].'.php';
			 	}
                    //echo XERCMS.$TagFile;
	 	 	 	if(is_file($TagFile) === false) {
                         $TagFile = XERCMS.'XerCMS/Utils/tag/XerCMS_'.$name.'.php';
                         //echo $TagFile;exit;
                         if(is_file($TagFile) === false) {
                              return 'TAG['.$name.'] is not exits!';
                         }
	 	 	 	}
	 	 	 	X::import($TagFile,null);
	 	 	 	$XERCMS[$CLASS] = new $CLASS();
	 	 	}
			$method = isset($param['method']) && !empty($param['method']) ? $param['method'] : $name;
			if(method_exists($XERCMS[$CLASS],$method)) {
			     return $XERCMS[$CLASS]->$method($param,$html,$layer);
			} else return 'TAG['.$name.'] METHOD['.$method.'] is not exits!';
	 	}
	 	return 'Unknown TAG!';
	}
	 
	public function el() {
	 	while(preg_match('/{XERCMS:([a-z0-9\#]+)([^\}]*?)}(.*?){end:\\1}/is',$this->html)) {
	 	 	$this->html = $this->preg('/{XERCMS:([a-z0-9\#]+)([^\}]*?)}(.*?){end:\\1}/is',function($match){return X::$compiler->tag($match[1],$match[2],$match[3]);},$this->html);
	 	}
	}
	
	private function embed($name) {
	 	if($this->embeds === NULL)
	 	 	$this->embeds = ini('embed');
	 	if(isset($this->embeds[$name]) == false)
	 	 	return 'No embed!';
	 	$data = Cache::fetchSql('SELECT * FROM xercms_embed_template WHERE name = \''.$name.'\'',0);
	 	$ret = '';
	 	foreach($data as $v) {
	 	 	$ret .= '<?php embed('.AtoS($v).'); ?>';
	 	}
	 	return $ret;
	}	 

	public function preg($pattern,$replacement,$subject,$eval = true) {
	     if(!$eval)
		     return preg_replace($pattern,$replacement,$subject);
	     if(function_exists('preg_replace_callback')) {
		     return preg_replace_callback($pattern,$replacement,$subject);
		} else {
		     if(preg_match_all($pattern,$subject,$match)) {
			     $max = count($match);
				foreach($match[0] as $k=>$v) {
				     $temp[$k][0] = $v;//,$match[1][$k]);		   
					for($i = 1;$i<$max;$i++) {
					     $temp[$k][$i] = $match[$i][$k];
					}
				}
				//print_R($temp);
			     foreach($temp as $k=>$v) {
			          $result = $replacement($v);
				     $subject = substr_replace($subject,$result,strpos($subject,$v[0]),strlen($v[0]));
				}
			}
			return $subject;
		}
     }
	 
	public function file($dir = 'template') {
          static $header = '<?php !defined(\'XERCMS\') && exit(\'Access Denied\');$G = &X::$G; ?>';
	     return $this->cache($dir,$this->cacheId,$header.$this->html); 
	}
	 
	public function cache($dir,$file,$data) {
	     if($this->cInst == NULL) {
		     X::import('cache');
			$this->cInst = new cache();
			$this->cInst->Set(INC.'Caches/');
		} 
		$this->cInst->push($dir.'/'.$file,$data);
		return $this->cInst->file;
	}
	 
	public function version() { 
	     $this->html = strtr($this->html,array('{VERSION}'=>'Powered by <a href="http://www.XERCMS.com" target="_blank">XerCMS</a>'));
	}	 
	 
     public function sparse($html,$return = false) {
          $this->html = $html;$this->values();
          $this->i();$this->v();$this->txt();$this->el();
          return $return ? $this->html : null;      
     }
      
	public function parse() {
	     $this->sub();
		$this->php('hide');$this->ads();
          $this->i();$this->el();	
		$this->values();
		$this->v();$this->txt();
		$this->version();
		$this->fun();
		$this->php('show');  
	}
}
?>